home *** CD-ROM | disk | FTP | other *** search
- /*
- +----------------------------------------------------+
- | Thunderbird Software |
- +----------------------------------------------------+
- | Filespec : Serial.c |
- | Date : October 24, 1991 |
- | Time : 15:03 |
- | Revision : 1.1 |
- | Update: August 29, 1994 |
- +----------------------------------------------------+
- | Programmer: Scott Andrews |
- | Address : 5358 Summit RD SW |
- | City/State: Pataskala, Ohio |
- | Zip : 43062 |
- +----------------------------------------------------+
- | Released to the Public Domain |
- +----------------------------------------------------+
- */
-
- /*
- +----------------------------------------------------------+
- | Call open_serial to install the interrupt handler |
- | You must call close_serial before exiting your program |
- | or a machine crash will occur! |
- +----------------------------------------------------------+
- */
-
- #include <stdlib.h>
- #include <dos.h>
- #include <string.h>
- #include "serial.h"
- #include "queue.h"
- #include "portable.h"
-
- QUEUE *Serial_In_Queue;
- QUEUE *Serial_Out_Queue;
-
- OLD_COMM_PARAMS old_comm_params;
- COMM_STATUS comm_status;
-
- void (_interrupt _far *oldvector_serial )();
- /* save addr for intr handler */
-
- int ComBase; /* Comm port address */
- int IrqNum; /* Comm interrupt request */
-
- int OpenComPort ( char Port ) /* install int. handler */
- {
- unsigned status;
- int retval = -1;
-
- /* allocate input and output queues */
-
- Serial_In_Queue = alloc_queue( SerInBufSize );
- if ( (QUEUE *) 0 == Serial_In_Queue)
- return retval;
- Serial_Out_Queue = alloc_queue( SerOutBufSize );
- if ( (QUEUE *) 0 == Serial_Out_Queue)
- {
- free ( Serial_In_Queue );
- return retval;
- }
- retval = 0;
-
- /* Setup Comm base port address and IRQ number */
-
- switch ( Port)
- {
- case '1': ComBase = 0x3F8; IrqNum = 4; break;
- case '2': ComBase = 0x2F8; IrqNum = 3; break;
- case '3': ComBase = 0x3E8; IrqNum = 4; break;
- case '4': ComBase = 0x2E8; IrqNum = 3; break;
- default : ComBase = 0x3F8; IrqNum = 4; break;
- }
- old_comm_params.int_enable = IN_PORT ( ComBase + INT_EN );
- OUT_PORT ( ComBase + INT_EN, 0 ); /* turn off comm interrupts */
-
- /* save old comm parameters */
-
- old_comm_params.line = IN_PORT ( ComBase + LINE_CNTRL );
- old_comm_params.modem = IN_PORT ( ComBase + MODEM_CNTRL );
- status = IN_PORT ( ComBase + LINE_CNTRL );
- OUT_PORT ( ComBase + LINE_CNTRL, (unsigned char) status | 0x80 );
- old_comm_params.baud_lsb = IN_PORT ( ComBase + BAUD_LSB );
- old_comm_params.baud_msb = IN_PORT ( ComBase + BAUD_MSB );
- status = IN_PORT ( ComBase + LINE_CNTRL );
- OUT_PORT ( ComBase + LINE_CNTRL, (unsigned char) status | 0x7F );
- status = OUT2 | DTR; /* DTR/OUT2 must be set! */
- OUT_PORT ( ComBase + MODEM_CNTRL, (unsigned char) status );
-
- /* get serial port address/vector */
-
- oldvector_serial = (void(_interrupt _far *)(void))GETVECT(IrqNum + 8 );
-
- /* set our interrupt handler */
-
- SETVECT ( IrqNum + 8, serial );
-
- /* save the PIC */
-
- old_comm_params.int_cntrl = IN_PORT ( 0x21 );
- status = ( 1 << IrqNum); /* calculate int enable bit */
- status = ~status;
-
- /* ok enable comm ints */
-
- OUT_PORT ( 0x21, (unsigned char) old_comm_params.int_cntrl &
- (unsigned char) status );
- return retval;
- }
-
- void CloseComPort ( void )
- {
- int status;
-
- /* restore UART to previous state */
-
- OUT_PORT ( ComBase + INT_EN, (unsigned char) 0 );
- OUT_PORT ( ComBase + MODEM_CNTRL,
- (unsigned char) old_comm_params.modem );
- status = IN_PORT ( ComBase + LINE_CNTRL );
- OUT_PORT ( ComBase + LINE_CNTRL,
- (unsigned char) status | 0x80 );
- OUT_PORT ( ComBase + BAUD_LSB,
- (unsigned char) old_comm_params.baud_lsb );
- OUT_PORT ( ComBase + BAUD_MSB,
- (unsigned char) old_comm_params.baud_msb );
- OUT_PORT ( ComBase + LINE_CNTRL,
- (unsigned char) old_comm_params.line );
- OUT_PORT ( 0x21, (unsigned char) old_comm_params.int_cntrl );
-
- /* restore old interrupt handler */
-
- SETVECT ( IrqNum + 8, oldvector_serial );
-
- /* free input and output queues */
-
- free ( Serial_In_Queue );
- free ( Serial_Out_Queue );
- return;
- }
-
- void InitComPort ( char Baud[], char Databits,
- char Parity, char Stopbits )
- {
- int status;
- long baudrate;
- unsigned divisor;
-
- /* set baud rate */
-
- status = IN_PORT ( ComBase + LINE_CNTRL );
- OUT_PORT ( ComBase + LINE_CNTRL,
- (unsigned char) status | 0x80 );
- baudrate = atol ( Baud );
- if ( baudrate == 0)
- baudrate = 2400L;
- divisor = (unsigned) ( 115200L / baudrate);
- OUT_PORT ( ComBase + BAUD_LSB,
- (unsigned char) ( divisor & 0x00FF) );
- OUT_PORT ( ComBase + BAUD_MSB,
- (unsigned char) ( ( divisor >> 8) & 0x00FF) );
- status = 0x00;
-
- /* set parity */
-
- switch ( Parity) /* set parity value */
- {
- case 'O': /* odd parity */
- case 'o':
- status = 0x08; break;
-
- case 'E': /* even parity */
- case 'e':
- status = 0x18; break;
-
- case 'S': /* stick parity */
- case 's':
- status = 0x28; break;
-
- case 'N': /* no parity */
- case 'n':
- default : status = 0x00;
- }
-
- /* set number data bits */
-
- switch ( Databits)
- {
- case '5':
- break;
-
- case '6':
- status = status | 0x01;
- break;
-
- case '7':
- status = status | 0x02;
- break;
-
- case '8':
- default :
- status = status | 0x03;
- }
-
- /* set number stop bits */
-
- switch ( Stopbits)
- {
- case '2':
- status = status | 0x04;
- break;
-
- case '1':
- default :
- ;
- }
- OUT_PORT ( ComBase + LINE_CNTRL, (unsigned char) status );
- status = OUT2 | DTR; /* DTR/OUT2 must be set! */
- OUT_PORT ( ComBase + MODEM_CNTRL, (unsigned char) status );
-
- /* enable serial interrupts */
-
- OUT_PORT ( ComBase + INT_EN, RX_INT | ERR_INT | RS_INT );
- return;
- }
-
- void DropDtr ( void )
- {
- int status;
-
- status = IN_PORT ( ComBase + MODEM_CNTRL );
- status &= 0xFE; /* turn off DTR bit */
- OUT_PORT ( ComBase + MODEM_CNTRL, (unsigned char) status );
- return;
- }
-
- void RaiseDtr ( void )
- {
- int status;
-
- status = IN_PORT ( ComBase + MODEM_CNTRL );
- status |= 0x01; /* turn on DTR bit */
- OUT_PORT ( ComBase + MODEM_CNTRL, (unsigned char) status );
- return;
- }
-
- int ComRecChar ( void )
- {
- return de_queue ( Serial_In_Queue );
- }
-
- int ComSendString ( char *string )
- {
- int retval;
- char *pointer;
- pointer = string;
-
- while ( *pointer)
- {
- retval = en_queue ( Serial_Out_Queue, *pointer );
- pointer++;
- }
- if ( 0x0 == (comm_status.modem & 0x40))
- RaiseDtr ();
- OUT_PORT ( ComBase + INT_EN, RX_INT | TBE_INT | ERR_INT | RS_INT );
- return retval;
- }
-
- int ComSendChar ( char character )
- {
- int retval;
-
- /* interrupt driven send */
-
- if ( 0x0 == (comm_status.modem & 0x40))
- RaiseDtr ();
- retval = en_queue ( Serial_Out_Queue, character );
- if ( - 1 != retval)
- OUT_PORT ( ComBase + INT_EN, RX_INT | TBE_INT | ERR_INT | RS_INT );
- return retval;
- }
-
- int ComStatus ( void )
- {
- unsigned status;
- unsigned retval;
-
- retval = IN_PORT ( ComBase + LINE_STATUS );
- retval = retval << 8;
- status = IN_PORT ( ComBase + MODEM_STATUS );
- retval = retval | status;
- if ( queue_empty ( Serial_In_Queue ))
- retval &= 0xFEFF;
- else retval |= 0x0100;
- return (int) retval;
- }
-
- void _interrupt _far serial ( void ) /* interrupt handler */
- {
- int temp;
-
- INT_OFF ();
- while ( 1)
- {
- comm_status.intrupt = IN_PORT ( ComBase + INT_ID );
- comm_status.intrupt &= 0x0f;
- switch ( comm_status.intrupt)
- {
- case 0x00: /* modem interrupt */
- comm_status.modem = IN_PORT( ComBase + MODEM_STATUS );
- break;
-
- case 0x02: /* xmit interrupt */
- if ( queue_empty ( Serial_Out_Queue ))
- OUT_PORT(ComBase + INT_EN, RX_INT|ERR_INT|RS_INT );
- else
- {
- temp = de_queue ( Serial_Out_Queue );
- if ( - 1 != temp)
- OUT_PORT ( ComBase + XMIT, temp );
- }
- break;
-
- case 0x04: /* receive interrupt */
- en_queue(Serial_In_Queue, (char)IN_PORT(ComBase + REC));
- break;
-
- case 0x06: /* line interrupt */
- comm_status.line = IN_PORT ( ComBase + LINE_STATUS );
- (void) IN_PORT ( ComBase + REC );
- en_queue ( Serial_In_Queue, '!' );
- break;
-
- default: /* No Mo` Left */
- comm_status.modem = IN_PORT ( ComBase + MODEM_STATUS );
- OUT_PORT ( 0x20, 0x20 );
- INT_ON ();
- return;
- } /* switch */
- } /* while */
- }
- /* End of Serial.C */
-